/*
Copyright (C) 2014  Johan Degraeve

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/gpl.txt>.

*/
package helpdiabetesj2me;

import java.util.Calendar;
import java.util.Date;
import javax.microedition.lcdui.*;
import javax.microedition.lcdui.Font;
import javax.microedition.rms.*;
public class ReadItemList extends MyCanvas implements CommandListener {

    static final String[] str_selitems = {"Geselecteerde items :"};
    static final String[] str_terug = {"Terug"};
    static final String[] str_kiezen = {"Kiezen"};
    static final String[] str_noitemss = {"Er werden nog geen voedingsmiddelen geselecteerd"};
    static final String[] str_gram = {"gram"};
    static final String[] str_amount_kh = {"gram kh"};
    static final String[] str_unitsins = {"IE"};

    //points to the record in selitemsrs that is first shown
    int shownrecid;
    //the line number that is inverted
    int highlightedLine;
    
    int bottomYOfShownRecord;
    int offSetForRecords;
 
    //temp variable used in paint()
    int tempid;
    
    private final Command Terug;
    private final Command Kiezen;
    
    /** Creates a new instance of ReadItemList 
     * @param userfont
     * @param midlet
     */
    public ReadItemList(Font userfont, HelpDiabetes midlet) {
         super(userfont,midlet);
         highlightedLine = 1;
         //don't need these inherited fields'
         enteredstring = null;
         resetexittimer();
         
         Terug = new Command(str_terug[HelpDiabetes.languageIndex],str_terug[HelpDiabetes.languageIndex],Command.EXIT,1);
         this.addCommand(Terug);
         Kiezen = new Command(str_kiezen[HelpDiabetes.languageIndex],str_kiezen[HelpDiabetes.languageIndex],Command.OK,2);
         this.setCommandListener(this);
    }

    /**
     * calculate and print insulin amount
     */
    private void showTotal (Graphics graphics) {
            Float ins;

            ins = ((Float)HDProperties.get("Ins_1"));
            
            if (!ins.Equal(Float.ZERO))  {
                Float totalCarbs = CalcTotalCarbs();
                paintstring((Float.Int(totalCarbs.Add(new Float(5,-1))).toString() + " " + str_amount_kh[HelpDiabetes.languageIndex] + " ==> " + Float.Int(totalCarbs.Div(ins).Mul(10).Add(new Float(5,-1))).Div(10).toString() + " " + str_unitsins[HelpDiabetes.languageIndex]).getBytes(),false,graphics,userfont,true);
                newline(0);
                newline(0);
            }
        }
    
    protected void paint(Graphics graphics) {
                x=0;y=0;
                graphics.setFont(userfont);

                graphics.setColor(255,255,255);
                graphics.fillRect(0, 0, scrwidth, scrhght);
                
                showTotal(graphics);
                
                paintstring(str_selitems[HelpDiabetes.languageIndex].getBytes(),false,graphics,userfont);
                x=0;y= y+fonthght;
                graphics.drawLine(0,y,scrwidth,y);
                y=y+1;
               
                try {
                   if (HelpDiabetes.getSelectedItemRs().getNumRecords() > 0) {
                       graphics.setClip(0,y,scrwidth,scrhght - y);
                       y = y - offSetForRecords;
                       tempid = 1;
                       RecordEnumeration enumer = HelpDiabetes.getSelectedItemRs().enumerateRecords(null,null,false);
                       while (enumer.hasNextElement() & (y < scrhght)) {
                            if (tempid == highlightedLine) {
                                if (y < graphics.getClipY()) {
                                    offSetForRecords = offSetForRecords - fonthght;
                                    repaint();
                                } else {
                                    shownrecid = enumer.nextRecordId();
                                    drawitem(true,HelpDiabetes.getSelectedItemRs().getRecord(shownrecid),graphics);
                                    //this is to make the line inverted for the whole width of the screen
                                    graphics.setColor(0,0,0);
                                    graphics.fillRect(x,y,scrwidth-x,fonthght);
                                    graphics.setColor(255,255,255);
                       
                                    //bottom of currently shown record = y
                                    bottomYOfShownRecord = y + fonthght;
                                    if (bottomYOfShownRecord > scrhght) {
                                        offSetForRecords = offSetForRecords  + fonthght;
                                        repaint();
                                    }
                                }
                            } else {
                                drawitem(false,enumer.nextRecord(),graphics);
                            }
                            x=0;y=y+fonthght;
                            tempid++;
                       }
                       graphics.setClip(0,0,scrwidth,scrhght);
                   } else {
                        this.removeCommand(Kiezen);
                        paintstring(str_noitemss[HelpDiabetes.languageIndex].getBytes(),false,graphics,userfont);
                   }
                   //method defined in parent class

               } catch (RecordStoreNotOpenException ex1) {
                   this.removeCommand(Kiezen);
                    paintstring(str_noitemss[HelpDiabetes.languageIndex].getBytes(),false,graphics,userfont);
               } catch (RecordStoreNotFoundException ex3) {
                   this.removeCommand(Kiezen);
                    paintstring(str_noitemss[HelpDiabetes.languageIndex].getBytes(),false,graphics,userfont);
               } catch (Exception ex2) {
                     
                    (new ReportException()).Report("Exception in ReadItemList.paint",ex2,false);
               } 
                
    }
    
    //method used in paint function
    //invert true means text to be drawn inverted
    //returnvalue 
    void drawitem(boolean invert,byte[] itemtodraw,Graphics graphics) {
        String amount1;
        int unit1;
        int i2;
        int recid1;
        int i1=0;
        int unitnumber;
        Float CarbAmount;
        String unit;
        try {
           //read the record from list with selected items 
           this.b = itemtodraw;
           this.blength = itemtodraw.length;
        
           // first get recid1, and amount
           i1 = getfirstsemicolon();
           recid1 = Integer.parseInt(new String(itemtodraw,0,i1));
           i2 = getnextsemicolon();
           amount1 = new String(itemtodraw,i1+1,i2-i1-1);
           
           // now get the unitnumber
           i1 = i2;
           i2 = getnextsemicolon();
           unitnumber = Integer.parseInt(new String(itemtodraw,i1+1,i2-i1-1),10);
           
           //now read the food item details
           b = new byte[maxblength];
           blength = FoodFile.getRecord(recid1,b,0);
           
           //from the recordstore, we need to get the unit
           //we need to skip a few columns in the food record store (with columns referring to the columns used in excel, depending on the value of unitnumber
           i1 = getfirstsemicolon();
           for (int itemp = 1;itemp < unitnumber;itemp++) {
                getnextsemicolon();
                getnextsemicolon();
                getnextsemicolon();
                getnextsemicolon();
                getnextsemicolon();
                i1  = getnextsemicolon();
           }
           
           i2 = getnextsemicolon();
           unit = new String(b,i1+1,i2-i1-1);

           CarbAmount = CalculateCarbAmount_in_b(unitnumber).Div(CalculateStandardAmount_in_b(unitnumber));
           
           //now paint the complete string consisting of amount, unitname and itemtext
           paintstring((
                       amount1 +
                       " " +
                       unit +
                       " "
                       ).getBytes(),invert,graphics,userfont);

           paintstring(b,blength,invert,graphics,userfont);

           paintstring(  (" (" + Float.Int((Float.parse(amount1,10)).Mul(CarbAmount).Mul(10).Add(new Float(5,-1))).Div(10) + " " + str_amount_kh[HelpDiabetes.languageIndex] + ")").getBytes(),invert,graphics,userfont);
        } catch (NumberFormatException nrforex) {// added june 2009, for support of own food items. If numberformatexception, it means the parseInt of recid1 failed, so it's a text
               // the exception occurred at statement recid1 = Integer.parseInt(new String(b,0,i1));
               // so we continue from there
            String fooditemname = new String(b,0,i1);
            i2 = getnextsemicolon();
            int percentage = Integer.parseInt(new String(b,i1+1,i2-i1-1),10);
            i1 = i2;
            i2 = blength;
            int amount = Integer.parseInt(new String(b,i1+1,i2-i1-1));
            paintstring ( (
                 amount + " "
                 + str_gram[HelpDiabetes.languageIndex]
                 + " "
                 + fooditemname
                 + " ("
                 + (new Float((long)amount)).Mul((long)percentage).Div(100).toString()
                 + " "
                 + str_amount_kh[HelpDiabetes.languageIndex]
                 + ")"
                    ).getBytes(),invert,graphics,userfont);
        } catch (InvalidRecordIDException iex) {
            ;
        }
        catch (Exception e) {
            System.out.println("e = " + e.toString());
            (new ReportException()).Report("Exception in ReadItemList.drawitem",e,false);
        }
    }
    
    //the method that will be called to show the list
    void showlist() {
        highlightedLine = 1;
        offSetForRecords = 0;
        
        bottomYOfShownRecord = 0;
        
        curdisp = midlet.getDisplay().getCurrent();
        midlet.getDisplay().setCurrent(this);
         
        try {
            if (HelpDiabetes.getSelectedItemRs().getNumRecords() > 0) {
                this.addCommand(Kiezen);
            }
        } catch (RecordStoreNotOpenException ex) {
            ex.printStackTrace();
        } catch (NullPointerException ex2) {
            //this happens if selitemsrs  doesn't exist
        } catch (RecordStoreNotFoundException ex3) {
            //this happens if selitemsrs  doesn't exist
        } catch (Exception ex) {
                             (new ReportException()).Report("Exception in ReadItemList",ex,false);
        }
        repaint();    
    }

    public void commandAction(Command command, Displayable displayable) {
        resetexittimer();
        if (command == Terug) {
            resetflipfloptimer(curdisp);
            midlet.getDisplay().setCurrent(curdisp);
        } else if (command == Kiezen) {
            keyPressed(getKeyCode(FIRE));
        }
    }
    
    //will be used to check if user presses up or down key, in order to scroll through the list
    public synchronized void keyPressed (int keyCode) {
        int unitnumber;
        String unit;
        int i2;
        int recid1;
        int i1=0;
        String oldamount;
            resetexittimer();
         switch(getGameAction(keyCode)) {
            case UP:
                    if (highlightedLine > 1) {
                        highlightedLine--;
                        repaint();
                    }
                    break;
            case DOWN:
                    try {
                        if (HelpDiabetes.getSelectedItemRs() != null) {
                            if (highlightedLine < HelpDiabetes.getSelectedItemRs().getNumRecords()) {
                                highlightedLine++;
                                repaint();
                            }
                        }
                    } catch (RecordStoreNotOpenException ex) {
                        (new ReportException()).Report("Exception in keypressed",ex,false);
                    } catch (Exception ex) {
                             (new ReportException()).Report("Exception in ReadItemList.keyPressed - FIRE",ex,false);
                    }
                    break;
            case FIRE:
                    
                        try {
                            if (HelpDiabetes.getSelectedItemRs() != null) {
                                if (HelpDiabetes.foodrs.getNumRecords() > 0) {
                                       //first read recid and amount from the list that holds the selected fooditems
                                       blength = HelpDiabetes.getSelectedItemRs().getRecord(shownrecid,b,0);
                                       i1 = getfirstsemicolon();
                                       recid1 = Integer.parseInt(new String(b,0,i1));
                                       i2 = getnextsemicolon();
                                       oldamount = new String(b,i1+1,i2-i1-1);
                                       i1=i2;
                                       i2 = getnextsemicolon();
                                       unitnumber = Integer.parseInt(new String(b,i1+1,i2-i1-1));
                                       // now get the contents of the foodrecord, just for the sake of getting the unit1
                                       //NOTE 2/11/2008 :
                                       //It's only necessary for older versions of the foodtable to try to parse the unit. In practice
                                       // it will always be a string, so parsing will always fail, and unit1 will always be 8.'
                                       //is to know if the method is called for adding a new item or for modifying an existing item.
                                       //Probably this could be changed, in just calling ItemSelected with the parameter unit = 1, always
                                       b = new byte[maxblength];
                                       blength = FoodFile.getRecord(recid1,b,0);
                                       HelpDiabetes.getitemfromuser.additem.ItemSelected(recid1,false,oldamount,shownrecid,unitnumber);
                                }
                            }
                        } catch (NumberFormatException nrex) {
                            ;//removed from old version, should not happen because we don't support own food item anymore
                            (new ReportException()).Report("NumberFormatException in ReadItemList.keyPressed - FIRE",nrex,false);
                        } catch (Exception ex) {
                             (new ReportException()).Report("Exception in ReadItemList.keyPressed - FIRE",ex,false);
                        }
                    break;
            case LEFT:
                resetflipfloptimer(curdisp);
                midlet.getDisplay().setCurrent(curdisp);
                break;
            case RIGHT:
                new ShowActiveInsulin(userfont, midlet);
                break;
               default:;
            } // end switch statement
    }

        String GetClassName() {
        return("ReadItemList");
    }

   public Float CalcTotalCarbs () {
       int unitnumber;
       int recid1;
       Float amount1;
       int i1,i2;
       RecordEnumeration enumer = null;
       Float returnValue = new Float(Float.ZERO);
       try {
           enumer = HelpDiabetes.getSelectedItemRs().enumerateRecords(null,null,false);
           while (enumer.hasNextElement()) {
               b = enumer.nextRecord();
               blength = b.length;
               // first get recid, and amount
               i1 = getfirstsemicolon();
               try {//added 10 june 2009 to support own food element, if record starts with text then
                   //next statement will throw exception which will be caught and handled
                   recid1 = Integer.parseInt(new String(b,0,i1));
                   i2 = getnextsemicolon();
                   amount1 = Float.parse(new String(b,i1+1,i2-i1-1),10);
                   // now get the unitnumber
                   i1 = i2;
                   i2 = getnextsemicolon();
                   unitnumber = Integer.parseInt(new String(b,i1+1,i2-i1-1),10);

                   b = new byte[maxblength];
                   blength = FoodFile.getRecord(recid1,b,0);
                  
                   returnValue = returnValue.Add( CalculateCarbAmount_in_b(unitnumber).Mul(amount1).Div(CalculateStandardAmount_in_b(unitnumber)));
                   
               } catch (NumberFormatException nrforex) {
                   //don't need the name of the fooditem so jump directly to next
                   i2 = getnextsemicolon();
                   int perc = Integer.parseInt(new String(b,i1+1,i2-i1-1));
                   i1 = i2;
                   i2 = b.length;
                   int amnt = Integer.parseInt(new String(b,i1+1,i2-i1-1));
                   returnValue = returnValue.Add(new Float((long)amnt).Mul(perc).Div(100));
                   b = new byte[maxblength];

               }
           }
       } catch (RecordStoreNotFoundException ex1) {
            ;//recordstore doesn't exist, so there's nothing to calculate, so do nothing, finally block will be called where 0 will be returned'
       } catch (Exception ex2) {
            (new ReportException()).Report("Exception in CalcItemsFromList",ex2,true);
       } finally {
            if( enumer != null) {
                enumer.destroy();
                enumer = null;
            }
            return returnValue;
       }
   }
   
}
